/**
 * Class represents a King Piece in chess game. Can move a single step in any of the following directions- forwards, backward, right, left and diagonal
 */

package model.pieces;

import java.awt.Point;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import model.Board;

public class King extends Piece {

	// private methods
	
	/**
	 * Gets all reachable free positions of a King piece on current turn, and removes positions that exceed
	 * the board's bounds
	 * @param gameBoard- chess game board
	 * @param freePositions- King's reachable free positions on current turn 
	 */
	private void filterOutOfBoundPositions(Board gameBoard, List<Point> freePositions) {

		// get an iterator for the list
		Iterator<Point> iter = freePositions.iterator();
		
		// scan list and remove positions that exceed board's bounds
		while (iter.hasNext()) {
			
			// check if current position is occupied
			Point currPosition = new Point(iter.next());
			if (gameBoard.notValidPosition(currPosition.x, currPosition.y)) {
				
				// remove current position
				iter.remove();
			}
		}
	}

	/**
	 * Gets all reachable free positions of a King piece on current turn, and removes positions that hold
	 * other pieces
	 * @param gameBoard- chess game board
	 * @param freePositions- King's reachable free positions on current turn
	 */
	private void filterOccupiedPositions(Board gameBoard, List<Point> freePositions) {

		// get an iterator for the list
		Iterator<Point> iter = freePositions.iterator();
		
		// scan list and remove occupied positions
		while (iter.hasNext()) {
			
			// check if current position is occupied
			Point currPosition = new Point(iter.next());
			if (gameBoard.getPiece(currPosition.x, currPosition.y) != null) {
				
				// remove current position
				iter.remove();
			}
		}
	}
	
	/**
	 * Gets all reachable positions of a King piece on current turn, and removes positions that hold
	 * friendly pieces
	 * @param gameBoard- chess game board
	 * @param opponentPositions- King's reachable positions on current turn that hold opponent pieces
	 */
	private void filterFriendlyPiecesPositions(Board gameBoard, List<Point> opponentPositions) {

		// get an iterator for the list
		Iterator<Point> iter = opponentPositions.iterator();
		
		// scan list and remove occupied positions
		while (iter.hasNext()) {
			
			// check if current position is occupied
			Point currPosition = new Point(iter.next());
			if (gameBoard.getPiece(currPosition.x, currPosition.y) != null && gameBoard.getPiece(currPosition.x, currPosition.y).sameTeam(this)) {
				
				// remove current position
				iter.remove();
			}
		}
	}
	
	
	// protected methods
	
	/**
	 * Gets reference to the game board and Kings's current position on board.
	 * Returns all 8-type neighboring points that are free 
	 */
	@Override
	protected List<Point> getAvailableFreePositions(Board gameBoard, Point srcPoint) {
		
		// initialize free reachable positions list
		List<Point> freePositions = new LinkedList<Point>();
		
		// scan all neighboring positions
		for (int i = -1 ; i <= 1 ; ++i) {
			for (int j = -1 ; j <= 1 ; ++j) {
		
				// make current move
				Point currPosition = new Point(srcPoint);
				currPosition.translate(i, j);
				
				// add reachable position
				freePositions.add(currPosition);
			}
		}
		
		// filter out of bound positions
		filterOutOfBoundPositions(gameBoard, freePositions);
				
		// filter out occupied positions
		filterOccupiedPositions(gameBoard, freePositions);
	
		// return list with all valid free positions
		return freePositions;
	}
	
	/**
	 * Gets reference to the game board and Kings's current position on board.
	 * Returns all 8-type neighboring points that hold an enemy piece 
	 */
	@Override
	protected List<Point> getAvailableOpponentPositions(Board gameBoard, Point srcPoint) {

		// initialize list of reachable opponent's positions
		List<Point> opponentPositions = new LinkedList<Point>();
		
		// scan all neighboring positions
		for (int i = -1 ; i <= 1 ; ++i) {
			for (int j = -1 ; j <= 1 ; ++j) {
				
				// make current move
				Point currPosition = new Point(srcPoint);
				currPosition.translate(i, j);
				
				// add reachable position
				opponentPositions.add(currPosition);
			}
		}
		
		// filter out of bound positions
		filterOutOfBoundPositions(gameBoard, opponentPositions);
				
		// filter out positions with friendly pieces
		filterFriendlyPiecesPositions(gameBoard, opponentPositions);
		
		// return list of position in range found
		return opponentPositions;
	}
	
	// public methods
	
	/**
	 * Constructor- creates a new King assigned to given player
	 * @param isFirstPlayer- indicates if assigned to first player or not
	 */
	public King(boolean isFirstPlayer) {
		// use base class's constructor to set members
		super(isFirstPlayer);
	}
	
	/**
	 * Returns a King of the same team
	 */
	@Override
	public Piece clone() { return new King(super.getPlayer()); }
}